/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package jfemtest;

import BounderyPack.Bounderies;
import BounderyPack.Boundery;
import BounderyPack.BounderyNodePair;
import BounderyPack.BounderyParams;
import BounderyPack.DBoundery;
import FEMSolver.FEMMainMatrixGenerator;
import FEMSolver.GradientMethod;
import FEMSolver.LagrangeMulti;
import FEMSolver.MPI;
import FEMSolver.MyPenaltyIteration;
import FEMSolver.overRelaxsationProjectionMethod;
import MathLib.triangulation.SaveStructures.Node;
import MathLib.triangulation.SaveStructures.Triangle;
import MathLib.triangulation.SaveStructures.TriangleL;
import OptionsPack.OptionsStorage;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Scanner;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

/**
 *
 * @author mark
 */
public class Main {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) throws FileNotFoundException {
            double eps = 1E-9;
            OptionsStorage options = new OptionsStorage();
            options.F = "100";
            //options.FolderPath = "C:\\Documents and Settings\\mark\\My Documents\\NetBeansProjects\\MySimpleFEM\\New Folder\\New Folder1";
            //options.FolderPath = "C:\\Users\\mark_o\\Documents\\NetBeansProjects\\MySimpleFEM\\New Folder\\New Folder\\";
            options.FolderPath = "C:\\Users\\marko\\Documents\\workspace\\MySimpleFEM\\New Folder\\New Folder\\New Folder\\123\\tmp";
//            options.FolderPath = "C:/Users/mark_o/workspace/MyFEM/New Folder";
            //options.FolderPath = "C:\\Documents and Settings\\mark\\My Documents\\NetBeansProjects\\MySimpleFEM\\New Folder\\";
            options.kx = 1;
            options.ky = 1;
            String FilePath = options.FolderPath;
            ArrayList<Triangle> TrList = null;
            ArrayList<Node> NodeList = null;
            //ArrayList<BounderyNodePair> BounNodeList = null;
            ArrayList<Integer> NodeList1 = new ArrayList<Integer>();
            ArrayList<Integer> NodeList2 = new ArrayList<Integer>();
         try {
            Scanner in = new Scanner(new FileInputStream(FilePath+"\\file.1.ele"));
            TrList = new ArrayList<Triangle>();
            int n = in.nextInt();
            in.nextInt();
            in.nextInt();
            for (int i = 0; i < n; i++) {
                in.next();
                //TrList.add(new TriangleQ(Integer.parseInt(in.next()), Integer.parseInt(in.next()), Integer.parseInt(in.next()),Integer.parseInt(in.next()), Integer.parseInt(in.next()), Integer.parseInt(in.next())));
                TrList.add(new TriangleL(Integer.parseInt(in.next()), Integer.parseInt(in.next()), Integer.parseInt(in.next())));
            }
            NodeList = getNodes(FilePath+"\\file.1.node");
            get(FilePath+"\\file.1.poly", NodeList1, NodeList2);
            //BounNodeList = get(FilePath+"\\file.1.poly", NodeList);

        } catch (FileNotFoundException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        }
            Bounderies bo = new Bounderies();
            ArrayList<Node> BoundsNodeList = generateBoundsNode(NodeList);

            ArrayList<Node> BoundsNodeListD = new ArrayList<Node>();
            ArrayList<Node> BoundsNodeListN = new ArrayList<Node>();
            ArrayList<Node> BoundsNodeListN1 = new ArrayList<Node>();
            for (int i = 0; i < BoundsNodeList.size(); i++) {
                Node node = BoundsNodeList.get(i);
                //if(Math.abs(node.x)==0.5){
                if((node.x)==0.5){
                //if((Math.abs( (node.y)-node.x-3 )<0.001)||(Math.abs( (node.y)+node.x-3 )<0.001)){
                    //if(((node.y)==1.0)&&((node.x)==1.0)){continue;}
                    BoundsNodeListD.add(node);
                }
                if((node.x)==-0.5){
                //if((Math.abs( (node.y)-node.x-3 )<0.001)||(Math.abs( (node.y)+node.x-3 )<0.001)){
                    //if(((node.y)==1.0)&&((node.x)==1.0)){continue;}
                    BoundsNodeListD.add(node);
                }
                //if((node.y)==0.5){
                //    BoundsNodeListD.add(node);
                //}
//                if(((node.y)==0.5)&&(Math.abs(node.x)!=0.5)){
//                if(((Math.abs(node.y))==0.5)){
                if(((node.y)==-0.5)&&((node.x)!=0.5)){
                //if((Math.abs( (node.y)-node.x-1 )<0.001)||(Math.abs( (node.y)+node.x-1 )<0.001)){
                    BoundsNodeListN.add(node);
                }

            }
            ArrayList<BounderyNodePair> temppp = transform(NodeList1, NodeList2, BoundsNodeListD, NodeList);
            
//            bo.getPyankare().add(new Boundery(new BounderyParams(2, "1", "1", "1"), transform(NodeList1, NodeList2, BoundsNodeListD, NodeList)));
//            bo.getDirihlet().add(new DBoundery(new BounderyParams(0, "1", "0", ""), BoundsNodeList));
            bo.getDirihlet().add(new DBoundery(new BounderyParams(0, "1", "5", ""), BoundsNodeListD));
//            bo.getDirihlet().add(new DBoundery(new BounderyParams(0, "1", "20", ""), BoundsNodeListN1));
//            bo.getDirihlet().add(new DBoundery(new BounderyParams(0, "1", "0", ""), BoundsNodeListN));
//            bo.getDirihlet().add(new DBoundery(new BounderyParams(0, "1", "20", ""), BoundsNodeListN));
//            bo.getNapivPronukluvist().add(new DBoundery(new BounderyParams(3, "15", "1", "1"), BoundsNodeListN));
//            bo.getNapivPronukluvist2().add(new Boundery(new BounderyParams(3, "15", "1", "1"), temppp));
//            bo.getNapivPronukluvist().add(new DBoundery(new BounderyParams(3, "5", "1", "1"), BoundsNodeListN1));
            bo.getNapivPronukluvist2().add(new Boundery(new BounderyParams(3, "5", "1", "1"), transform(NodeList1, NodeList2, BoundsNodeListN, NodeList)));
//            bo.getNayman().add(new Boundery(new BounderyParams(1, "5", "1", ""), temppp));





            FEMMainMatrixGenerator gen = new FEMMainMatrixGenerator();
            //FEMQuadraticTRMainMatrixGenerator gen = new FEMQuadraticTRMainMatrixGenerator();
            gen.eps = eps;
            gen.setF(options.F);
            gen.setKx(options.kx);
            gen.setKy(options.ky);
            
            gen.setNodeList(NodeList);
            gen.setTriangleList(TrList);
            gen.setBounds(bo);
            
            gen.setPe(0);
            gen.setPekle(0);

            gen.key=true;

            gen.GenerateLU();
        //try {

            ArrayList<Double> C = new ArrayList<Double>();
            for (int i = 0; i < gen.A2.getN(); i++) {
                C.add(5.0);
            }
//
//            overRelaxsationProjectionMethod ORPM = new overRelaxsationProjectionMethod(bo.getNapivPronukluvist(),System.out,gen.mas,gen.A2, C, gen.b, 0.25, eps);
//            ORPM.BoundsNodeList = BoundsNodeList;
//            ORPM.calc();

//            GradientMethod gr = new GradientMethod(bo.getNapivPronukluvist(), gen.b, gen.A2, gen.mas);
//            gr.calc();

//            LagrangeMulti lm = new LagrangeMulti(gen.A2, gen.b, bo.getNapivPronukluvist2(), System.out, gen.mas);
            LagrangeMulti lm = new LagrangeMulti(gen.A2, gen.b, bo.getNapivPronukluvist2(), NodeList, TrList, System.out, null);
            lm.calc();
//            gen.SolveLU(FilePath + "\\fileLU.txt");

//            MPI mpi = new MPI(bo.getNapivPronukluvist2(), System.out, gen.mas, gen.A2, gen.b);
//            mpi.calc();






//            JFrame fr = new JFrame();
//        fr.setSize(400, 400);
//        JTextArea txt = new JTextArea();
//        txt.setAutoscrolls(true);
//        JScrollPane JS = new JScrollPane(txt);
//        fr.getContentPane().add(JS);
//        fr.setVisible(true);
//        fr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//        MyPenaltyIteration pen = new MyPenaltyIteration(5, eps, gen.b, gen.A2,gen.A3, null, txt, FilePath, gen.mas, bo.getNapivPronukluvist(),bo.getNapivPronukluvist2(), NodeList, TrList);//5, 0.01, gen.b, gen.A2, bo.getNapivPronukluvist(), txt, gen.mas);
//
//        //MyPenaltyIterationOld.MaxIter = 5000;
//        //MyPenaltyIterationOld pen = new MyPenaltyIterationOld(5, 0.01, gen.b, gen.A2, bo.getNapivPronukluvist(), txt, gen.mas);
//        pen.outPath = FilePath+"\\penaltyRES.txt";
//
//        pen.bLive = gen.bLive;
//            pen.execute();

//            gen.SolveLU(FilePath + "\\fileLU.txt");





        //} catch (FileNotFoundException ex) {
            //Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        //}

    }

    public static ArrayList<Node> getNodes(String FilePath) throws FileNotFoundException{
        Scanner in = new Scanner((new FileInputStream(FilePath)));
            ArrayList<Node> NodeList  = new ArrayList<Node>();
            int n = in.nextInt();
            in.nextInt();
            in.nextInt();
            in.nextInt();
            for (int i = 0; i <n; i++) {
                in.next();
                NodeList.add(new Node( ( Double.parseDouble(in.next()) ), ( Double.parseDouble(in.next()) ) , ( isTrue(Integer.parseInt(in.next())) ) ,i ));
                System.out.println(NodeList.get(i).x+"\t"+NodeList.get(i).y);
            }
            return NodeList;
    }

    private static boolean isTrue(int s){
        if(s==0){return false;}else{return true;}
    }

    public static ArrayList<Node>  generateBoundsNode(ArrayList<Node> NodeList){
        ArrayList<Node> BoundsNodeList = new ArrayList<Node>();
        //BoundsNodePosList = new ArrayList<Integer>();
        if(NodeList==null){return null;}
        for(int i =0;i<NodeList.size();i++){
            Node tmp = NodeList.get(i);
            if(tmp.IsOnBoundery){
                BoundsNodeList.add(new Node(tmp.x, tmp.y, true,tmp.Number));
            }
        }
        return  BoundsNodeList;
    }

    public static ArrayList<BounderyNodePair> get(String FilePath,ArrayList<Node> NodeList) throws FileNotFoundException{
        Scanner in = new Scanner((new FileInputStream(FilePath)));
            ArrayList<BounderyNodePair> BounNodeList  = new ArrayList<BounderyNodePair>();
            in.nextInt();
            in.nextInt();
            in.nextInt();
            in.nextInt();
            int n = in.nextInt();
            in.nextInt();
            for (int i = 0; i <n; i++) {
                in.nextInt();
                int A = in.nextInt();
                int B = in.nextInt();

                BounNodeList.add(new BounderyNodePair(NodeList.get(A-1), NodeList.get(B-1)));
                in.nextInt();
            }
            return BounNodeList;
    }

    public static void get(String FilePath,ArrayList<Integer> NodeList1,ArrayList<Integer> NodeList2) throws FileNotFoundException{
        Scanner in = new Scanner((new FileInputStream(FilePath)));
            in.nextInt();
            in.nextInt();
            in.nextInt();
            in.nextInt();
            int n = in.nextInt();
            in.nextInt();
            for (int i = 0; i <n; i++) {
                in.nextInt();
                NodeList1.add(in.nextInt());
                NodeList2.add(in.nextInt());
                in.nextInt();
            }
    }




    public static ArrayList<BounderyNodePair> transform(ArrayList<Integer> NodeList1,ArrayList<Integer> NodeList2, ArrayList<Node> BNodes,ArrayList<Node> Nodes){
        ArrayList<BounderyNodePair> res = new ArrayList<BounderyNodePair>();
        //while (!BNodes.isEmpty()) {
        for(int i=0;i<BNodes.size();i++){
            Node A = BNodes.get(i);
            //BNodes.remove(0);
            int pos = NodeList1.indexOf(A.Number+1);
            if(pos>=0){
                Node B = Nodes.get(NodeList2.get(pos)-1);
                if(BNodes.contains(B)){
                    res.add(new BounderyNodePair(A, B));
                    //System.out.println((A.Number+1)+"\t\t"+(B.Number+1));
                }
                NodeList1.remove(pos);
                NodeList2.remove(pos);
            }
            pos = NodeList2.indexOf(A.Number+1);
            if(pos>=0){
                Node B = Nodes.get(NodeList1.get(pos)-1);
                if(BNodes.contains(B)){
                    res.add(new BounderyNodePair(A, B));
                    //System.out.println((B.Number+1)+"\t\t"+(A.Number+1));
                }
                NodeList1.remove(pos);
                NodeList2.remove(pos);
            }
        }

        return res;
    }

}
